package com.tech.freak.pyp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;

import com.tech.freak.pyp.data.PicoyPlaca.PYP;
import com.tech.freak.pyp.model.CityRestriction;
import com.tech.freak.pyp.model.LicensePlate;

public class Utils {
	
	private static final String 	TAG = "Utils";
	
	public static final String 		CITY = "city";
	public static final String 		LICENSE = "license";
	public static final String 		UPDATE_WIDGET = "com.tech.freak.pyp.UPDATE_WIDGET";
	public static final String 		UPDATE_SUCCESS = "com.tech.freak.pyp.UPDATE_DATA_SUCCESS";
	public static final String 		UPDATE_ERROR = "com.tech.freak.pyp.UPDATE_DATA_ERROR";
	public static final String 		UPDATE_ONGOING = "com.tech.freak.pyp.UPDATE_DATA_ONGOING";
	
	static final String TRUE = "true";
	static final String FALSE = "false";
	private static final String FIRST_RUN = "first_run";
	
	static final SimpleDateFormat DAY_WEEK = new SimpleDateFormat("EEEEE",Locale.getDefault());
	
	private static final String[] pypProjection = new String[] { 
		PYP._ID,
		PYP.CITY, 
		PYP.MONDAY, 
		PYP.TUESDAY,
		PYP.WEDNSEDAY,
		PYP.THURSDAY,
		PYP.FRIDAY,
		PYP.SATURDAY,
		PYP.SUNDAY};
	
	//this class should not be instantiated
	private Utils(){
		
	}
	
	public static void saveInfo(Context c, String label, String value){
		SharedPreferences credentials = c.getSharedPreferences(c.getString(R.string.info_filename), Context.MODE_PRIVATE);
		SharedPreferences.Editor editor = credentials.edit();
		//save user info
		editor.putString(label, value);
		//commit changes
		editor.commit();
	}
	
	public static String getInfo(Context c, String label){
		SharedPreferences pref = c.getSharedPreferences(c.getString(R.string.info_filename), Context.MODE_PRIVATE);
		return pref.getString(label, "");
	}
	
	public static void saveWidgetInfo(Context c, int appWidgetId, String label, String value){
		SharedPreferences pref = c.getSharedPreferences(c.getString(R.string.widget_info_filename)+appWidgetId, Context.MODE_PRIVATE);
		SharedPreferences.Editor editor = pref.edit();
		//save user info
		editor.putString(label, value);
		//commit changes
		editor.commit();
	}
	
	public static String getWidgetInfo(Context c, int appWidgetId, String label){
		SharedPreferences pref = c.getSharedPreferences(c.getString(R.string.widget_info_filename)+appWidgetId, Context.MODE_PRIVATE);
		return pref.getString(label, "");
	}
	
	public static LicensePlate calculatePyP(Context context, CityRestriction[] cityRestrictions, String city, String license) {
		LicensePlate result = null;
		
		if(city!=null){
			for (int i = 0; i < cityRestrictions.length; i++) {
				if(cityRestrictions[i].getCity().equalsIgnoreCase(city)){
					result = new LicensePlate();
					//Set city
					result.setCity(city);
					//Get day of the week
					Calendar newCal = Calendar.getInstance(Locale.US);
					//Transform day from locale to array index
					int day = (newCal.get( Calendar.DAY_OF_WEEK )+5) % 7;
					if (day>= 0 && day < cityRestrictions[i].getRestrictions().length){
						if(license!=null){
							//Set restrictions for whole day
							result.setRestrictions(cityRestrictions[i].getRestrictions()[day]);
							if(cityRestrictions[i].getRestrictions()[day].contains(license)){
								//Set restricted license
								result.setLicensePlate(R.drawable.sad);
								result.setRestricted(true);
							}
							else{
								//Set non restricted license
								result.setLicensePlate(R.drawable.happy);
								result.setRestricted(false);
							}
						}
					}
				}
			}
		}
		
		
		return result;
	}
		
	public static void deleteWidgetInfo(Context c, int appWidgetId) {
		SharedPreferences pref = c.getSharedPreferences(c.getString(R.string.widget_info_filename)+appWidgetId, Context.MODE_PRIVATE);
		SharedPreferences.Editor editor = pref.edit();
		//save user info
		editor.clear();
		//commit changes
		editor.commit();
		
	}
	
	public static void scheduleWidgetUpdate(Context context){
	    // We want the alarm to go off 30 seconds from now.
        Calendar c = Calendar.getInstance();
        c.roll(Calendar.DATE, true);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 00);
        long firstTime = c.getTimeInMillis();
        
        //Create the pending intent to update our widget
        Intent i = new Intent();
        i.setAction(Utils.UPDATE_WIDGET);
        PendingIntent updateWidgetIntent = PendingIntent.getBroadcast(context, 001, i , PendingIntent.FLAG_UPDATE_CURRENT);

        // Schedule the alarm!
        AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        //am.set(AlarmManager.RTC, firstTime, updateWidgetIntent);
        am.setRepeating(AlarmManager.RTC, firstTime, AlarmManager.INTERVAL_DAY, updateWidgetIntent);

        Log.i(TAG, "Alarm Scheduled ");
	}

	public static Cursor getPypsFromDB(ContentResolver cr) {
		Cursor c = cr.query(PYP.CONTENT_URI, pypProjection, null, null, null);
		return c;
	}

	public static void updateCity(ContentResolver cr, long _id,
			JSONArray city_values) throws JSONException {
		Uri city = ContentUris.withAppendedId(PYP.CONTENT_URI, _id);
		
		ContentValues values = new ContentValues();
		
		values.put(PYP.MONDAY, city_values.getString(0));
		values.put(PYP.TUESDAY, city_values.getString(1));
		values.put(PYP.WEDNSEDAY, city_values.getString(2));
		values.put(PYP.THURSDAY, city_values.getString(3));
		values.put(PYP.FRIDAY, city_values.getString(4));
		values.put(PYP.SATURDAY, city_values.optString(5));
		values.put(PYP.SUNDAY, city_values.optString(6));
		
		cr.update(city, values, null, null);
		
	}

	public static void insertCities(ContentResolver cr, JSONObject pyps) {
		if(pyps!=null && pyps.length() > 0){
			JSONArray names = pyps.names();
			int length = names.length();
			ContentValues values = new ContentValues();
			JSONArray city_values;
			for (int i = 0; i<length ; i++) {
				values.clear();
				try {
					values.put(PYP.CITY, names.getString(i));
					//Get all day values
					city_values = pyps.getJSONArray(names.getString(i));
					values.put(PYP.MONDAY, city_values.getString(0));
					values.put(PYP.TUESDAY, city_values.getString(1));
					values.put(PYP.WEDNSEDAY, city_values.getString(2));
					values.put(PYP.THURSDAY, city_values.getString(3));
					values.put(PYP.FRIDAY, city_values.getString(4));
					values.put(PYP.SATURDAY, city_values.optString(5));
					values.put(PYP.SUNDAY, city_values.optString(6));
					
					cr.insert(PYP.CONTENT_URI, values);
					
	
				}catch (JSONException e) {
					Log.e(TAG, "Error while inserting new cities", e);
				}catch (Exception e){
					Log.e(TAG, "Error while inserting new cities", e);
				}
				
			}
		}

	}
	
	public static String convertStreamToString(InputStream is) throws IOException {
		/*
         * To convert the InputStream to String we use the
         * Reader.read(char[] buffer) method. We iterate until the
         * Reader return -1 which means there's no more data to
         * read. We use the StringWriter class to produce the string.
         */
        if (is != null) {
            Writer writer = new StringWriter();

            char[] buffer = new char[1024];
            try {
                Reader reader = new BufferedReader(
                        new InputStreamReader(is, "UTF-8"));
                int n;
                while ((n = reader.read(buffer)) != -1) {
                    writer.write(buffer, 0, n);
                }
            } finally {
                is.close();
            }
            return writer.toString();
        } else {        
            return "";
        }
	}

	public static CityRestriction[] getCityRestrictions(ContentResolver cr) {
		CityRestriction[] result=null;
		Cursor c = cr.query(PYP.CONTENT_URI, pypProjection, null, null, null);
		
		if(c!=null){
			try{
				if(c.moveToFirst()){
					result = new CityRestriction[c.getCount()];
					int i=0;
					do {
						result[i] = new CityRestriction();
						result[i].setCity(c.getString(c.getColumnIndex(PYP.CITY)));
						String[] restrictions = {
								c.getString(c.getColumnIndex(PYP.MONDAY)),
								c.getString(c.getColumnIndex(PYP.TUESDAY)),
								c.getString(c.getColumnIndex(PYP.WEDNSEDAY)),
								c.getString(c.getColumnIndex(PYP.THURSDAY)),
								c.getString(c.getColumnIndex(PYP.FRIDAY)),
								c.getString(c.getColumnIndex(PYP.SATURDAY)),
								c.getString(c.getColumnIndex(PYP.SUNDAY)),
								};
						result[i].setRestrictions(restrictions);
						i++;
					} while (c.moveToNext());
				
				}
			}catch (Exception e) {
				Log.e(TAG, "Error while getting city restrictions", e);
			}
			finally{
				c.close();
			}
		}
		
		return result;
	}
	
	public static boolean firstRun(Context context) {
		if(Utils.getInfo(context, FIRST_RUN).equalsIgnoreCase(TRUE)){
			return false;
		}
		return true;
	}
	
	public static void preloadDB(Context context) {
		InputStream i = context.getResources().openRawResource(R.raw.info);
		try {
			String info = Utils.convertStreamToString(i);
			JSONObject pyps = new JSONObject(info);
			Utils.insertCities(context.getContentResolver(), pyps);
			
			Utils.saveInfo(context, FIRST_RUN, TRUE);
		} catch (IOException e) {
			Log.e(TAG,"Error while parsing json document",e);
		} catch (JSONException e) {
			Log.e(TAG,"Error while parsing json document",e);
		}

		
	}
}
